#!/bin/sh

local uVid uPid uMa uPr uSe
local sVe sMo sRe

local modeswitch="/usr/bin/usb_modeswitch"


log() {
	logger -t "usb-modeswitch" "$@"
}

sanitize() {
	sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@"
}

find_scsi_attrs() {
	[ -n "$DEVPATH" ] && [ -d /sys/$DEVPATH/host* ] && {
		log "$DEVICENAME is a SCSI device, waiting for it to settle..."
		local timeout=20
		while [ $((--timeout)) -ge 0 ]; do
			[ -d /sys/$DEVPATH/host*/target* ] && {
				local scsi_dir
				for scsi_dir in /sys/$DEVPATH/host*/target*/*; do
					[ -d "$scsi_dir" ] || break
					case "$scsi_dir" in
						*/host*/target*/*:*:*:*)
							sVe=$(sanitize "$scsi_dir/vendor")
							sMo=$(sanitize "$scsi_dir/model")
							sRe=$(sanitize "$scsi_dir/rev")

							log "$DEVICENAME: Vendor=${sVe:-?} Model=${sMo:-?} Revision=${sRe:-?}"
							return 0
						;;
					esac
				done
			} || {
				sleep 1
			}
		done
		log "$DEVICENAME: Failed to get SCSI attributes!"
	}

	return 1
}

find_usb_attrs() {
	local usb_dir="/sys/$DEVPATH"
	[ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}"

	uVid=$(cat "$usb_dir/idVendor")
	uPid=$(cat "$usb_dir/idProduct")
	uMa=$(sanitize "$usb_dir/manufacturer")
	uPr=$(sanitize "$usb_dir/product")
	uSe=$(sanitize "$usb_dir/serial")

	log "$DEVICENAME: Manufacturer=${uMa:-?} Product=${uPr:-?} Serial=${uSe:-?}"
}

match_config_tag() {
	local conf="$1"
	local tag="$2"

	case "${conf##*/}" in
		*:*$tag=*)
			local cmp; eval "cmp=\$$tag"
			local pat="${conf#*:$tag=}"; pat="${pat%%:*}"
			case "$cmp" in
				*$pat*) return 0 ;;
				*) return 1 ;;
			esac
		;;
	esac

	return 0
}

match_config() {
	local conf="$1"
	local tag

	for tag in uMa uPr uSe sVe sMo sRe; do
		match_config_tag "$conf" "$tag" || return 1
	done

	return 0
}



if [ "$ACTION" = add ]; then
	[ -d "/etc/usb_modeswitch.d" ] && [ -x "$modeswitch" ] && {
		case "$DEVICENAME" in
			*-*:*.*) : ;;
			*) exit 0 ;;
		esac

		find_usb_attrs

		local candidates=0
		local conf configs
		for conf in /etc/usb_modeswitch.d/$uVid:$uPid*; do
			[ -f "$conf" ] || break
			configs="${configs:+$configs }$conf"
			$((candidates++))
		done

		# Found more than one candidate, read SCSI attributes and find the best match
		[ $candidates -gt 1 ] && {
			find_scsi_attrs
			for conf in $configs; do
				match_config "$conf" && {
					configs="$conf"
					candidates=1
					break
				}
			done
		}

		# If a candidate is remaining, start usb-modeswitch
		[ -n "$configs" ] && {
			log "$DEVICENAME: Selecting ${configs%% *} for mode switching"
			# ugly workaround, but working for all hw we got for testing
			switching_done=0
			switching_tries=0
			local usb_dir="/sys/$DEVPATH"
			[ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}"
			while [ $switching_done -lt 1 -a $switching_tries -le 6 ]; do
				$modeswitch -v $uVid -p $uPid -I -D -n -s 30 -c "${configs%% *}"
				if [ $(sanitize "$usb_dir/idProduct") = $uPid ]; then
					log "$DEVICENAME: Switching seemingly failed"
					sleep 1
				else
					switching_done=1
				fi
				switching_tries=$(( $switching_tries + 1 ))
			done
		}
	}
fi
